using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using SkinnedModel;

namespace A_stain_on_the_planet
{
    class Fish
    {
        FishLevel m_Level;
        FishLevelSurvival m_LevelSurvival;
        Vector2 m_Position;
        Vector2 m_Velocity;
        Texture2D m_texFish;
        Rectangle m_Rect;
        BoundingBox m_BoundingBox;
        BoundingBox m_Hoofd;
        int m_FrameCount;
        int m_FrameRate;
        int m_Time;
        int m_eatingFrame = 0;
        int m_DeathFrame = 0;
        int m_flikkereing = 0;
        float m_immortalityTimer;
        float m_Swimtimmer;
        bool m_immortality = true;
        bool m_HasBeenSwipped = true;
        bool m_IsGoingFast = false;
        bool m_LeftLooking;
        bool m_HasEaten = false;
        bool m_IsDead = false;
        bool m_StopAnimation = false;
        System.Random generator = new System.Random();

        Model currentModel;
        Model m_ModelDie;
        Model m_ModelEat;
        Model m_ModelFloat;
        Model m_ModelSwim;
        Model m_ModelDead;
        AnimationPlayer animationPlayer;
        TimeSpan TimeSpanAnim;

        public Fish(FishLevel level, Vector2 Position, Texture2D texture, Vector2 velocity)
        {
            m_Level = level;
            m_Position = Position;
            m_texFish = texture;
            m_Velocity = velocity;
        }

        public Fish(FishLevelSurvival level, Vector2 Position, Texture2D texture, Vector2 velocity)
        {
            m_LevelSurvival = level;
            m_Position = Position;
            m_texFish = texture;
            m_Velocity = velocity;
        }

        public void Initialize(ContentManager content)
        {
            generator = new Random();

            int rand = generator.Next(0, 3);

            if (rand == 0)
            {
                m_ModelDie = content.Load<Model>(@"Animation\FishDie_2006");
                m_ModelEat = content.Load<Model>(@"Animation\FishEat_2006");
                m_ModelFloat = content.Load<Model>(@"Animation\FishFloat_2006");
                m_ModelSwim = content.Load<Model>(@"Animation\FishSwim_2006");
                m_ModelDead = content.Load<Model>(@"Animation\FishDead");
                currentModel = m_ModelSwim;
            }

            if (rand == 1)
            {
                m_ModelDie = content.Load<Model>(@"Animation\FishDie_B");
                m_ModelEat = content.Load<Model>(@"Animation\FishEat_B");
                m_ModelFloat = content.Load<Model>(@"Animation\FishFloat_B");
                m_ModelSwim = content.Load<Model>(@"Animation\FishSwim_B");
                m_ModelDead = content.Load<Model>(@"Animation\FishDead_B");
                currentModel = m_ModelSwim;
            }

            if (rand == 2)
            {
                m_ModelDie = content.Load<Model>(@"Animation\FishDie_R");
                m_ModelEat = content.Load<Model>(@"Animation\FishEat_R");
                m_ModelFloat = content.Load<Model>(@"Animation\FishFloat_R");
                m_ModelSwim = content.Load<Model>(@"Animation\FishSwim_R");
                m_ModelDead = content.Load<Model>(@"Animation\FishDead_R");
                currentModel = m_ModelSwim;
            }

            // Look up our custom skinning information.
            SkinningData skinningData = currentModel.Tag as SkinningData;

            if (skinningData == null)
                throw new InvalidOperationException
                    ("This model does not contain a SkinningData tag.");

            //Create an animation player, and start decoding an animation clip.
            animationPlayer = new AnimationPlayer(skinningData);

            AnimationClip clip = skinningData.AnimationClips["Take 001"];

            animationPlayer.StartClip(clip);

            m_HasBeenSwipped = true;

            int ImageHeight = m_texFish.Height/9;
            int ImageWidth = m_texFish.Width / 4;

            m_Rect = new Rectangle((int)m_Position.X, (int)m_Position.Y, (int)(ImageWidth), (int)(ImageHeight));

            m_BoundingBox = new BoundingBox(new Vector3(m_Rect.X, m_Rect.Y, 0),
                                             new Vector3(m_Rect.X + m_Rect.Width, m_Rect.Y + m_Rect.Height, 0));
            m_immortalityTimer = 0;
        }

        public void Update(GameTime gametime)
        {
            if (currentModel == m_ModelDie)
            {
                if (animationPlayer.EndClip == true)
                {
                    m_StopAnimation = true;

                    currentModel = m_ModelDead;
                }
            }

            if(m_StopAnimation == false) animationPlayer.Update(gametime.ElapsedGameTime, true, Matrix.Identity);

            if (m_immortalityTimer <= 4000)
            {
                m_immortalityTimer += gametime.ElapsedGameTime.Milliseconds; 
            }

            if (m_immortalityTimer >= 4000 && m_immortality == true) m_immortality = false;


            if (m_DeathFrame >= 8)
            {
                m_Velocity.Y = -3;
                m_Velocity.X = 0;
            }

            else
            {
                if (m_Velocity.X < 0) m_Velocity.X += 0.1f;
                if (m_Velocity.Y < 0) m_Velocity.Y += 0.1f;
                if (m_Velocity.X > 0) m_Velocity.X -= 0.1f;
                if (m_Velocity.Y > 0) m_Velocity.Y -= 0.1f;
            }

            m_Swimtimmer++;
            if (m_Swimtimmer >= 100)
            {
                int rand = generator.Next(50, 100);
                int rand2 = generator.Next(50, 100);

                m_Velocity.X = rand / 20;
                m_Velocity.Y = rand2 / 20;

                rand = generator.Next(1, 3);
                rand2 = generator.Next(1, 3);

                if (rand == 1) m_Velocity.X = -m_Velocity.X;
                if (rand2 == 1) m_Velocity.Y = -m_Velocity.Y;

                m_Swimtimmer = 0;
            }

            if (m_IsGoingFast == true || IsDead == true)
            {
                m_Swimtimmer = 0;
            }

            if (((m_Velocity.X <= 3.5f && m_Velocity.X >= -3.5f) && (m_Velocity.Y <= 3.5f && m_Velocity.Y >= -3.5f))) 
            {
                if(m_FrameCount ==2)
                m_IsGoingFast = false;
            }
            else m_IsGoingFast = true;

            if (m_Velocity.X >= 0.5f) m_LeftLooking = false;
            if (m_Velocity.X <= -0.5f) m_LeftLooking = true;

            m_Rect.X += (int)m_Velocity.X;
            m_Rect.Y += (int)m_Velocity.Y;

            m_Position.X = m_Rect.X;
            m_Position.Y = m_Rect.Y;

            m_BoundingBox.Min.X = m_Rect.X;
            m_BoundingBox.Max.X = m_Rect.X + m_Rect.Width;

            m_BoundingBox.Min.Y = m_Rect.Y;
            m_BoundingBox.Max.Y = m_Rect.Y + m_Rect.Height;

            if (m_LeftLooking == true)
            {
                m_Hoofd.Min = new Vector3((int)m_Position.X, (int)m_Position.Y + 10, 0);
                m_Hoofd.Max = new Vector3((int)m_Position.X + 40, (int)m_Position.Y + 50, 0);
            }

            if (m_LeftLooking == false)
            {
                m_Hoofd.Min = new Vector3((int)m_Position.X + 115, (int)m_Position.Y + 10, 0);
                m_Hoofd.Max = new Vector3((int)m_Position.X + 155, (int)m_Position.Y + 50, 0);
            }
            

            ++m_Time;

            if (m_Time >= 3)
            {
                if (m_eatingFrame <= 8 && m_HasEaten == true)
                {
                    ++m_eatingFrame;
                }

                else if (m_IsDead == true)
                {
                    if (m_DeathFrame <= 7) m_DeathFrame++;
                }

                else
                {
                    m_FrameCount += m_FrameRate;

                    if (m_FrameCount <= 0)
                    {
                        m_FrameRate = 1;
                    }

                    if (m_FrameCount >= 8)
                    {
                        m_FrameRate = -1;
                    }
                }

                m_Time = 0;
            }
        }

        public void Draw(GameTime gametime, SpriteBatch spritebatch, GraphicsDeviceManager graphics)
        {
            if (currentModel != m_ModelDead)
            {
                if (m_eatingFrame <= 8 && m_HasEaten == true)
                {
                    if (currentModel != m_ModelEat)
                    {
                        currentModel = m_ModelEat;

                        SkinningData skinningData = currentModel.Tag as SkinningData;

                        if (skinningData == null)
                            throw new InvalidOperationException
                                ("This model does not contain a SkinningData tag.");

                        //Create an animation player, and start decoding an animation clip.
                        animationPlayer = new AnimationPlayer(skinningData);

                        AnimationClip clip = skinningData.AnimationClips["Take 001"];

                        animationPlayer.StartClip(clip);
                    }
                }

                else if (m_IsDead == true)
                {
                    if (currentModel != m_ModelDie)
                    {
                        currentModel = m_ModelDie;

                        SkinningData skinningData = currentModel.Tag as SkinningData;

                        if (skinningData == null)
                            throw new InvalidOperationException
                                ("This model does not contain a SkinningData tag.");

                        //Create an animation player, and start decoding an animation clip.
                        animationPlayer = new AnimationPlayer(skinningData);

                        AnimationClip clip = skinningData.AnimationClips["Take 001"];

                        animationPlayer.StartClip(clip);
                    }
                }

                else if (m_HasBeenSwipped == true)
                {
                    if (!m_IsGoingFast)
                    {
                        if (currentModel != m_ModelFloat)
                        {                        
                            TimeSpan time = new TimeSpan(0, 0, 0, 0, 190);
                            TimeSpan time2 = new TimeSpan(0, 0, 0, 0, 210);

                            TimeSpan time3 = new TimeSpan(0, 0, 0, 0, 590);
                            TimeSpan time4 = new TimeSpan(0, 0, 0, 0, 610);

                            if (currentModel == m_ModelSwim && ((animationPlayer.CurrentTime >= time && animationPlayer.CurrentTime <= time2) || (animationPlayer.CurrentTime >= time3 && animationPlayer.CurrentTime <= time4)))
                            {

                                currentModel = m_ModelFloat;

                                SkinningData skinningData = currentModel.Tag as SkinningData;



                                if (skinningData == null)
                                    throw new InvalidOperationException
                                        ("This model does not contain a SkinningData tag.");

                                //Create an animation player, and start decoding an animation clip.
                                animationPlayer = new AnimationPlayer(skinningData);

                                AnimationClip clip = skinningData.AnimationClips["Take 001"];

                                animationPlayer.StartClip(clip);
                            }

                            else if (currentModel != m_ModelSwim)
                            {
                                currentModel = m_ModelFloat;

                                SkinningData skinningData = currentModel.Tag as SkinningData;



                                if (skinningData == null)
                                    throw new InvalidOperationException
                                        ("This model does not contain a SkinningData tag.");

                                //Create an animation player, and start decoding an animation clip.
                                animationPlayer = new AnimationPlayer(skinningData);

                                AnimationClip clip = skinningData.AnimationClips["Take 001"];

                                animationPlayer.StartClip(clip);
                            }
                        }
                    }

                    if (m_IsGoingFast)
                    {
                        if (currentModel != m_ModelSwim)
                        {
                            currentModel = m_ModelSwim;

                            SkinningData skinningData = currentModel.Tag as SkinningData;

                            if (skinningData == null)
                                throw new InvalidOperationException
                                    ("This model does not contain a SkinningData tag.");

                            //Create an animation player, and start decoding an animation clip.
                            animationPlayer = new AnimationPlayer(skinningData);

                            AnimationClip clip = skinningData.AnimationClips["Take 001"];

                            animationPlayer.StartClip(clip);
                        }
                    }
                }
            }
        }

        public Vector2 Position
        {
            get { return m_Position; }
            set { m_Position = value; }
        }

        public Vector2 Velocity
        {
            get { return m_Velocity; }
            set { m_Velocity = value; }
        }

        public BoundingBox Boundingbox
        {
            get { return m_BoundingBox; }
        }

        public BoundingBox Hoofd
        {
            get { return m_Hoofd; }
        }

        public bool HasbeenSwiped
        {
            get { return m_HasBeenSwipped; }
            set { m_HasBeenSwipped = value; }
        }

        public bool HasEaten
        {
            get { return m_HasEaten; }
            set { m_HasEaten = value; }
        }

         public bool IsDead
        {
            get { return m_IsDead; }
            set { m_IsDead = value; }
        } 
 
        public bool Isimmortal
        {
            get { return m_immortality; }
            set { m_immortality = value; }
        }

        public void Draw3D(GameTime gametime, GraphicsDeviceManager graphics)
        {
            GraphicsDevice device = graphics.GraphicsDevice;

            // Compute camera matrices.
            Matrix view = Matrix.CreateTranslation(0, 0, 0) *
                          Matrix.CreateRotationY(MathHelper.ToRadians(0)) *
                          Matrix.CreateRotationX(MathHelper.ToRadians(0)) *
                          Matrix.CreateLookAt(new Vector3(0, 0, 100),
                                              new Vector3(0, 0, 0), Vector3.Up);

            Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
                                                                    device.Viewport.AspectRatio,
                                                                    1,
                                                                    10000);
                    
            Matrix world;

            if (m_LeftLooking == true) world = Matrix.CreateRotationY((float)Math.PI);
            else  world = Matrix.CreateRotationY(0);

            float x = m_Position.X;
            x -= 400;
            x /= 400;
            x *= 70;
            if (m_LeftLooking == false) x += 22;
            else x += 5;

            float y = m_Position.Y;
            y -= 250;
            y /= 250;
            y *= 43;
            y += 7;

            world.Translation = new Vector3(x, -y, 0);


            if (currentModel != m_ModelDead)
            {
                Matrix[] bones = animationPlayer.GetSkinTransforms();
                //Render the skinned mesh.
                foreach (ModelMesh mesh in currentModel.Meshes)
                {
                    foreach (SkinnedEffect effect in mesh.Effects)
                    {
                        effect.SetBoneTransforms(bones);

                        effect.View = view;
                        effect.Projection = projection;

                        effect.EnableDefaultLighting();

                        effect.SpecularColor = new Vector3(0.25f);
                        effect.SpecularPower = 16;
                    }
                }
            }
            currentModel.Draw(world, view, projection);
        }
    }
}
